{-# OPTIONS -Wall #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  DirectoryDiff.Report
-- Copyright   :  (c) Stephen Peter Tetley 2012
-- License     :  BSD3
--
-- Maintainer  :  stephen.tetley@gmail.com
-- Stability   :  experimental
-- Portability :  to be determined
--
-- Pretty printer
--
-----------------------------------------------------------------------------


module DirectoryDiff.Report
  (
    title
  , reportDirDiffs
  , reportFileDiffs 

  ) where

import DirectoryDiff.Compare
import DirectoryDiff.ResolvedSyntax
import DirectoryDiff.VersionNumber

import Text.PrettyPrint.SPretty

import Data.List ( isInfixOf )

title :: Resolved -> Resolved -> Doc
title old new = 
        text "Directory diff" <+> text versionString <+> text "- comparing:"
    $+$ text "---------------------------------"
    $+$ line
    $+$ text "Old:" 
    $+$ text "----"
    $+$ text (res_path_to_root old)
    $+$ ppDateTime (resolvedDateTime old)
    $+$ countLine (length $ res_directories old) (length $ res_files old)
    $+$ line
    $+$ text "New:" 
    $+$ text "----"
    $+$ text (res_path_to_root new)
    $+$ ppDateTime (resolvedDateTime new)
    $+$ countLine (length $ res_directories new) (length $ res_files new)
    $+$ line
  where
    countLine = \i j -> int i <+> text "directories, " <+> int j <+> text "files."


reportDirDiffs :: Resolved -> Resolved -> Doc
reportDirDiffs old new = 
        text "Directory changes"
    $+$ text "-----------------"
    $+$ line
    $+$ text "Deleted:" 
    $+$ nest 2 ( int (length dels) <+> text "directories deleted."
                 $+$ (ppListWith text dels))
    $+$ directoriesNotCurrOrPrev dels
    $+$ line
    $+$ text "Added:" 
    $+$ nest 2 ( int (length adds) <+> text "directories added."
                 $+$ ppListWith text adds )
    $+$ line
    $+$ text "Moved:" 
    $+$ nest 2 ( int (length movs) <+> text "directories moved."
                 $+$ ppListWith ppMove movs)
    $+$ line
  where
    (ChangeSet { change_set_deleted = dels
               , change_set_added   = adds
               , change_set_moved   = movs }) = diffDirectories "Current" old new


directoriesNotCurrOrPrev :: [String] -> Doc
directoriesNotCurrOrPrev = 
    next . filter (neither (isInfixOf "\\Current") (isInfixOf "\\Previous"))
  where
    next [] = empty
    next xs =     text "Of the directories above, the following" 
              <+> int (length xs)
              <+> text "directories do not have Current or Previous in their path:"
              $+$ vcat (map text xs)
               

neither :: (a -> Bool) -> (a -> Bool) -> (a -> Bool)
neither p1 p2 = \a -> not (p1 a) && not (p2 a)


reportFileDiffs :: Resolved -> Resolved -> Doc
reportFileDiffs old new = 
        text "File changes"
    $+$ text "------------"
    $+$ line
    $+$ text "Deleted:" 
    $+$ nest 2 ( int (length dels) <+> text "files deleted."
                 $+$ ppListWith text dels )
    $+$ filesNotCurrOrPrev dels
    $+$ line
    $+$ text "Added:" 
    $+$ nest 2 ( int (length adds) <+> text "files added."
                 $+$ ppListWith text adds )
    $+$ line
    $+$ text "Moved:" 
    $+$ nest 2 ( int (length movs) <+> text "files moved."
                 $+$ ppListWith ppMove movs )
    $+$ line
  where
    (ChangeSet { change_set_deleted = dels
               , change_set_added   = adds
               , change_set_moved   = movs }) = diffFiles "Current" old new


filesNotCurrOrPrev :: [String] -> Doc
filesNotCurrOrPrev = 
    next . filter (neither (isInfixOf "\\Current") (isInfixOf "\\Previous"))
  where
    next [] = empty
    next xs =     text "Of the files above, the following" 
              <+> int (length xs)
              <+> text "files do not have Current or Previous in their path:"
              $+$ vcat (map text xs)
               


ppListWith :: (a -> Doc) -> [a] -> Doc
ppListWith fn = vcat . map fn



ppMove :: Moved -> Doc
ppMove (Moved { old_path = old, new_path = new }) = 
   text "    " <+> text new $+$ text "was:" <+> text old $+$ line

ppDateTime :: DateTime -> Doc
ppDateTime a = year <+> day
  where
    year = intersperse (char '/') [ nat2 $ dt_day a
                                  , nat2 $ dt_month a
                                  , nat4 $ dt_year a ]
    day  = nat2 (dt_hour a) <> colon <> nat2 (dt_min a)

